package com.px.baolaiapi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.px.common.api.CommonPage;
import com.px.common.constant.Constant;
import com.px.mbg.mapper.WhMapper;
import com.px.mbg.model.*;
import com.px.baolaiapi.mapper.WhBomMapper;
import com.px.baolaiapi.page.WhPage;
import com.px.baolaiapi.service.*;
import com.px.baolaiapi.util.JwtTokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 库存信息V1 服务实现类
 * </p>
 *
 * @author 品讯科技
 * @since 2022-03-15
 */
@Transactional
@Service
public class WhServiceImpl extends ServiceImpl<WhMapper, Wh> implements IWhService {

    @Autowired
    private IBomService bomService;
    @Autowired
    private IWhRecordService whRecordService;
    @Autowired
    private JwtTokenUtils jwtTokenUtils;
    @Autowired
    private IStorageService storageService;
    @Autowired
    private IUnitMainService unitMainService;
    @Autowired
    private WhBomMapper whBomMapper;
    

    @Autowired
    private IOccupationService occupationService;

    /**
     * 通过编码查询库存信息
     *
     * @param code code
     * @return int
     */
    @Override
    public Wh queryWhByCode(String code, long storageId) {
        List<Wh> list = this.list(new QueryWrapper<Wh>().lambda().eq(Wh::getCode, code).eq(Wh::getStorageId, storageId));
        if (CollectionUtil.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<Wh> queryWhListByCode(String code) {
        return this.list(new QueryWrapper<Wh>().lambda().eq(Wh::getCode, code));
    }

    /**
     * 添加库存信息
     *
     * @param wh wh
     * @return int
     */
    @Override
    public int addWh(Wh wh) {
        //查询当前编码是否已经存在
        Wh wh1 = queryWhByCode(wh.getCode(), wh.getStorageId());
        if (ObjectUtil.isNotEmpty(wh1)) {
            return -1;
        }
        //判断当前该货品是不是bom原材料，并且需要增加字段标识来源
        Bom bom = bomService.queryBomByCode(wh.getCode());
        if (ObjectUtil.isNotEmpty(bom)) {
            wh.setSourceTyoe(Constant.WH_SOURCE_TYPE.BOM);
        }
        boolean save = this.save(wh);
        if (save) {
            //如果是新增的话，则需要将当前库存添加到记录中
            WhRecord whRecord = new WhRecord();
            whRecord.setWhId(wh.getId());
            whRecord.setAmount(new BigDecimal(0));
            whRecord.setRemark("初始化库存");
            whRecordService.inWhRecord(whRecord);
        }
        return save ? 1 : 0;
    }

    /**
     * 更新库存信息
     *
     * @param wh wh
     * @return int
     */
    @Override
    public int updateWh(Wh wh) {
        Wh wh2 = this.getById(wh.getId());
        if (ObjectUtil.isNotEmpty(wh2)) {
            BigDecimal oldBalance = wh2.getBalance();
            BigDecimal newBalance = wh.getBalance();
//            wh2.setCode();
            wh2.setName(wh.getName());
            wh2.setTexture(wh.getTexture());
            wh2.setWidth(wh.getWidth());
            wh2.setLongt(wh.getLongt());
            wh2.setThickness(wh.getThickness());
            wh2.setWeight(wh.getWeight());
            wh2.setPurpose(wh.getPurpose());
            wh2.setBalance(newBalance);
            wh2.setSafeBalance(wh.getSafeBalance());
            wh2.setSafeBalanceUpper(wh.getSafeBalanceUpper());
            wh2.setWtype(wh.getWtype());
            wh2.setWidthUnit(wh.getWidthUnit());
            wh2.setWeightUnit(wh.getWeightUnit());
            wh2.setLengthUnit(wh.getLengthUnit());
            wh2.setThicknessUnit(wh.getThicknessUnit());
            wh2.setSpecification(wh.getSpecification());
            wh2.setStockUnit(wh.getStockUnit());
            wh2.setSerialNumber(wh.getSerialNumber());
            wh2.setBatchNumber(wh.getBatchNumber());
            boolean b = this.updateById(wh2);
            if (b) {
                //如果是新增的话，则需要将当前库存添加到记录中
                WhRecord whRecord = new WhRecord();
                whRecord.setWhId(wh2.getId());

                Users user = jwtTokenUtils.getUser();
                whRecord.setRemark(user.getAccount() + "(" + user.getUsername() + ")" + "变更库存");
                if (newBalance.doubleValue() > oldBalance.doubleValue()) {
                    //入库
                    whRecord.setAmount(new BigDecimal(newBalance.doubleValue() - oldBalance.doubleValue()));
                    whRecordService.inWhRecord(whRecord);
                } else if (newBalance.doubleValue() < oldBalance.doubleValue()) {
                    //出库
                    whRecord.setAmount(new BigDecimal(oldBalance.doubleValue() - newBalance.doubleValue()));
                    whRecordService.outWhRecord(whRecord);
                } else {
                    //如果相等，只记录数量就行了
                    whRecord.setAmount(new BigDecimal(0));
                    whRecordService.inWhRecord(whRecord);
                }

            }
            return b ? 1 : 0;
        }
        return 0;
    }

    /**
     * 分页查询
     *
     * @param whPage wh页面
     * @return {@link CommonPage}
     */
    @Override
    public CommonPage queryWhPage(WhPage whPage) {

        //CommonPage commonPage = CommonPage.restPage(whOfStorageLocationMapper.queryWhRecordDetailPage(new Page<>(whRecordPage.getPageNum(), whRecordPage.getPageRow()), whRecordPage));

        Long organizationId = jwtTokenUtils.getOrganizationId();
        whPage.setOrganizationId(organizationId);
        CommonPage commonPage = CommonPage.restPage(whBomMapper.queryWhBomPage(new Page<>(whPage.getPageNum(), whPage.getPageRow()), whPage));
        List<WhBomRecord> WhBomRecordList = commonPage.getList();



        if (CollectionUtil.isNotEmpty(WhBomRecordList)) {
            List<JSONObject> jsonObjects = new ArrayList<>();
            for (WhBomRecord wh : WhBomRecordList) {


                Map<String, String> lengthMap = unitMainService.getItemMapByCode("长度");
                Map<String, String> weightMap = unitMainService.getItemMapByCode("重量");

                JSONObject jsonObject = JSONUtil.parseObj(wh);
                // 替换单位文字
                Map<String, Object> unitCN = bomService.getUnitCN(wh.getWidthUnit(), wh.getLengthUnit(), wh.getThicknessUnit(), wh.getWeightUnit(), wh.getStockUnit());
                jsonObject.putAll(unitCN);

                //时间去除尾数0
                if(ObjectUtil.isNotEmpty(jsonObject.get("bzjhgs"))) {
                    jsonObject.set("bzjhgs", Double.valueOf(jsonObject.get("bzjhgs").toString()));
                }
                if(ObjectUtil.isNotEmpty(jsonObject.get("djjsgs"))) {
                    jsonObject.set("djjsgs", Double.valueOf(jsonObject.get("djjsgs").toString()));
                }

                // 占用数量
                BigDecimal useNum = occupationService.queryOccupationQuantityByCode(wh.getCode());
                jsonObject.set("occupied", useNum);//已占用数量
                jsonObjects.add(jsonObject);
            }
            commonPage.setList(jsonObjects);
        }

        return commonPage;
    }



    /*@Override
    public CommonPage queryWhPage(WhPage whPage) {
        LambdaQueryWrapper<Wh> queryWrapper = Wrappers.lambdaQuery(Wh.class);
        queryWrapper.orderByDesc(Wh::getUpdatedTime);

        String code = whPage.getCode();
        if (StringUtils.isNotEmpty(code)) {
            queryWrapper.like(Wh::getCode, code);
        }
        Long storageId = whPage.getStorageId();
        if (storageId != null && storageId > 0) {
            queryWrapper.eq(Wh::getStorageId, storageId);
        }
        String texture = whPage.getTexture();
        if (StringUtils.isNotEmpty(texture)) {
            queryWrapper.like(Wh::getTexture, texture);
        }
        String name = whPage.getName();
        if (StringUtils.isNotEmpty(name)) {
            queryWrapper.like(Wh::getName, name);
        }
        Integer wtype = whPage.getWtype();
        if (wtype != null && wtype > 0) {
            queryWrapper.eq(Wh::getWtype, wtype);
        }

        CommonPage commonPage = CommonPage.restPage(this.page(new Page<>(whPage.getPageNum(), whPage.getPageRow()), queryWrapper));
        List<Wh> list = commonPage.getList();
        if (CollectionUtil.isNotEmpty(list)) {
            Map<String, String> lengthMap = unitMainService.getItemMapByCode("length");
            Map<String, String> weightMap = unitMainService.getItemMapByCode("weight");

            List<JSONObject> jsonObjects = new ArrayList<>();
            for (Wh wh : list) {
                JSONObject jsonObject = JSONUtil.parseObj(wh);
                Storage storage = storageService.getById(wh.getStorageId());
                if (ObjectUtil.isNotEmpty(storage)) {
                    jsonObject.set("storageName", storage.getName());
                }

                // 补充单位中文名称
                String widthUnit = wh.getWidthUnit();
                String widthUnitCN = lengthMap.getOrDefault(widthUnit, widthUnit);
                jsonObject.set("widthUnitCN", widthUnitCN);
                String lengthUnit = wh.getLengthUnit();
                String lengthUnitCN = lengthMap.getOrDefault(lengthUnit, lengthUnit);
                jsonObject.set("lengthUnitCN", lengthUnitCN);
                String thicknessUnit = wh.getThicknessUnit();
                String thicknessUnitCN = lengthMap.getOrDefault(thicknessUnit, thicknessUnit);
                jsonObject.set("thicknessUnitCN", thicknessUnitCN);
                String weightUnit = wh.getWeightUnit();
                String weightUnitCN = weightMap.getOrDefault(weightUnit, weightUnit);
                jsonObject.set("weightUnitCN", weightUnitCN);

                jsonObjects.add(jsonObject);
            }
            commonPage.setList(jsonObjects);
        }
        return commonPage;
    }*/

    /**
     * 通过编码查询库存信息
     *
     * @return int
     */
    @Override
    public BigDecimal queryWhCountByCode(String code) {
        BigDecimal bigDecimal = new BigDecimal(0);

        Long organizationId = jwtTokenUtils.getOrganizationId();
        List<Wh> whList = this.list(new QueryWrapper<Wh>().lambda().eq(Wh::getCode, code).eq(Wh::getOrganizationId,organizationId));

        // add :  添加筛选占用数量
        //List<Occupation> occupationList = occupationService.queryOccupations(saleOrderNo,code);
        List<Occupation> occupationList = occupationService.queryOccupations(code);
        BigDecimal userNum = new BigDecimal(0);
        for (Occupation occupation : occupationList) {
            userNum.add(occupation.getCount());
        }


        if (CollectionUtil.isNotEmpty(whList)) {
            for (Wh wh : whList) {
                bigDecimal = bigDecimal.subtract(wh.getBalance());
            }
        }
        return bigDecimal.subtract(userNum);
        //return bigDecimal;
    }

    @Override
    public BigDecimal queryWhQuantityByCode(String code) {
        BigDecimal bigDecimal = new BigDecimal(0);

        Long organizationId = jwtTokenUtils.getOrganizationId();
        List<Wh> whList = this.list(new QueryWrapper<Wh>().lambda().eq(Wh::getCode, code).eq(Wh::getOrganizationId,organizationId));

        if (CollectionUtil.isNotEmpty(whList)) {
            for (Wh wh : whList) {
                bigDecimal = bigDecimal.add(wh.getBalance());
            }
        }
        return bigDecimal;
    }

    @Override
    public boolean synchronizedWhInfo() throws Exception {
        List<Map<String, Object>> list = new ArrayList();
        if (CollectionUtil.isNotEmpty(list)) {
            List<Wh> addList = new ArrayList<>();
            List<Wh> updateList = new ArrayList<>();

            List<Wh> datas = this.list();

            for (Map<String, Object> stringObjectMap : list) {

                boolean isCreated = true;
                long organizationId = Long.parseLong(stringObjectMap.get("organizationId").toString());
                long materialId = Long.parseLong(stringObjectMap.get("materialId").toString());
                String materialCode = stringObjectMap.get("materialCode") == null ? "" : stringObjectMap.get("materialCode").toString();
                String materialName = stringObjectMap.get("materialName") == null ? "" : stringObjectMap.get("materialName").toString();

                String storageCode = stringObjectMap.get("storageCode") == null ? "" : stringObjectMap.get("storageCode").toString();
                String storageName = stringObjectMap.get("storageName") == null ? "" : stringObjectMap.get("storageName").toString();

                Double stockNum = stringObjectMap.get("stockNum") == null ? 0.00 : Double.parseDouble(stringObjectMap.get("stockNum").toString());
                String storeUOM = stringObjectMap.get("storeUOM") == null ? "" : stringObjectMap.get("storeUOM").toString();
                Double costNum = stringObjectMap.get("costNum") == null ? 0.00 : Double.parseDouble(stringObjectMap.get("costNum").toString());
                String costUOM = stringObjectMap.get("costUOM") == null ? "" : stringObjectMap.get("costUOM").toString();

                String lotCode = stringObjectMap.get("lotCode") == null ? "" : stringObjectMap.get("lotCode").toString();


                String storageType = stringObjectMap.get("storageType") == null ? "" : stringObjectMap.get("storageType").toString();
                //storageType = storageType.replaceAll("可用", "1").replaceAll("报废", "0");
                String dateStr = stringObjectMap.get("lastModifyDate") == null ? "" : stringObjectMap.get("lastModifyDate").toString();

                dateStr = dateStr.contains(".") ? dateStr.substring(0, dateStr.indexOf(".")) : dateStr;
                LocalDateTime lastModifyDate = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

                String cDateStr = stringObjectMap.get("createdOn") == null ? "" : stringObjectMap.get("createdOn").toString();
                cDateStr = cDateStr.contains(".") ? cDateStr.substring(0, cDateStr.indexOf(".")) : cDateStr;
                LocalDateTime createdOn = LocalDateTime.parse(cDateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                if (datas.size() > 0) {
                    List<Wh> infoList = datas.stream().filter(info -> info.getOrganizationId() == organizationId && info.getCode().equals(materialCode)  && info.getStorageCode().equals(storageCode)
                            && info.getBatchNumber().equals(lotCode)).collect(Collectors.toList());
                    if (infoList.size() > 0) {
                        isCreated = false;
                        //直接处理变更的数据
                        Wh info = infoList.get(0);
                        info.setBalance(new BigDecimal(stockNum.doubleValue()));
                        info.setCostNum(new BigDecimal(costNum.doubleValue()));
                        info.setLastModifyDate(lastModifyDate);
                        updateList.add(info);
                    }
                }

                //处理新增的
                if (isCreated) {
                    Wh info = new Wh();
                    info.setOrganizationId(organizationId);
                    info.setStorageCode(storageCode);
                    info.setStorageName(storageName);
                    info.setMaterialId(materialId);
                    info.setCode(materialCode);
                    info.setName(materialName);
                    info.setStoragetype(storageType);
                    info.setBalance(new BigDecimal(stockNum.doubleValue()));
                    info.setStockUnit(storeUOM);
                    info.setCostNum(new BigDecimal(costNum.doubleValue()));
                    info.setCostUom(costUOM);
                    info.setBatchNumber(lotCode);
                    info.setLastModifyDate(lastModifyDate);
                    info.setCreatedOn(createdOn);
                    addList.add(info);
                }
            }


            //添加
            if (CollectionUtil.isNotEmpty(addList)) {
                this.saveBatch(addList);
            }

            //更新
            if (CollectionUtil.isNotEmpty(updateList)) {
                this.updateBatchById(updateList);
            }

        }
        return true;

    }
    @Override
    public boolean synchronizedWhInfoNoDate() throws Exception {
        List<Map<String, Object>> list = new ArrayList();
        if (CollectionUtil.isNotEmpty(list)) {
            List<Wh> addList = new ArrayList<>();
            List<Wh> updateList = new ArrayList<>();

            List<Wh> datas = this.list();

            for (Map<String, Object> stringObjectMap : list) {

                boolean isCreated = true;
                long organizationId = Long.parseLong(stringObjectMap.get("organizationId").toString());
                long materialId = Long.parseLong(stringObjectMap.get("materialId").toString());
                String materialCode = stringObjectMap.get("materialCode") == null ? "" : stringObjectMap.get("materialCode").toString();
                String materialName = stringObjectMap.get("materialName") == null ? "" : stringObjectMap.get("materialName").toString();

                String storageCode = stringObjectMap.get("storageCode") == null ? "" : stringObjectMap.get("storageCode").toString();
                String storageName = stringObjectMap.get("storageName") == null ? "" : stringObjectMap.get("storageName").toString();

                Double stockNum = stringObjectMap.get("stockNum") == null ? 0.00 : Double.parseDouble(stringObjectMap.get("stockNum").toString());
                String storeUOM = stringObjectMap.get("storeUOM") == null ? "" : stringObjectMap.get("storeUOM").toString();
                Double costNum = stringObjectMap.get("costNum") == null ? 0.00 : Double.parseDouble(stringObjectMap.get("costNum").toString());
                String costUOM = stringObjectMap.get("costUOM") == null ? "" : stringObjectMap.get("costUOM").toString();

                String lotCode = stringObjectMap.get("lotCode") == null ? "" : stringObjectMap.get("lotCode").toString();


                String storageType = stringObjectMap.get("storageType") == null ? "" : stringObjectMap.get("storageType").toString();
                //storageType = storageType.replaceAll("可用", "1").replaceAll("报废", "0");
                String dateStr = stringObjectMap.get("lastModifyDate") == null ? "" : stringObjectMap.get("lastModifyDate").toString();
                dateStr = dateStr.contains(".") ? dateStr.substring(0, dateStr.indexOf(".")) : dateStr;
                LocalDateTime lastModifyDate = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

                String cDateStr = stringObjectMap.get("createdOn") == null ? "" : stringObjectMap.get("createdOn").toString();
                cDateStr = cDateStr.contains(".") ? cDateStr.substring(0, cDateStr.indexOf(".")) : cDateStr;
                LocalDateTime createdOn = LocalDateTime.parse(cDateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                if (datas.size() > 0) {
                    List<Wh> infoList = datas.stream().filter(info -> info.getOrganizationId() == organizationId && info.getCode().equals(materialCode)
                              && info.getBatchNumber().equals(lotCode)).collect(Collectors.toList());
                    if (infoList.size() > 0) {
                        isCreated = false;
                        //直接处理变更的数据
                        Wh info = infoList.get(0);
                        Integer result = info.getBalance().compareTo(new BigDecimal(stockNum.doubleValue()));
                        if (result != 0) {
                            info.setBalance(new BigDecimal(stockNum.doubleValue()));
                            info.setCostNum(new BigDecimal(costNum.doubleValue()));
                            updateList.add(info);
                        }
                    }
                }

                //处理新增的
                if (isCreated) {
                    Wh info = new Wh();
                    info.setOrganizationId(organizationId);
                    info.setStorageCode(storageCode);
                    info.setStorageName(storageName);
                    info.setMaterialId(materialId);
                    info.setCode(materialCode);
                    info.setName(materialName);
                    info.setStoragetype(storageType);
                    info.setBalance(new BigDecimal(stockNum.doubleValue()));
                    info.setStockUnit(storeUOM);
                    info.setCostNum(new BigDecimal(costNum.doubleValue()));
                    info.setCostUom(costUOM);
                    info.setBatchNumber(lotCode);
                    info.setLastModifyDate(lastModifyDate);
                    info.setCreatedOn(createdOn);
                    addList.add(info);
                }
            }


            //添加
            if (CollectionUtil.isNotEmpty(addList)) {
                this.saveBatch(addList);
            }

            //更新
            if (CollectionUtil.isNotEmpty(updateList)) {
                this.updateBatchById(updateList);
            }

        }
        return true;

    }

}
